package com.zhoug.router;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import com.alibaba.android.arouter.core.LogisticsCenter;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.launcher.ARouter;
import com.zhoug.logging.Logger;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

/**
 * 页面导航路由器
 *
 * @Author HK-LJJ
 * @Date 2020/3/19
 * @Description
 */
public class Router {
    private static final String TAG = ">>>Router";
    private static Router instance;

    /**
     * 单例
     *
     * @return
     */
    public static Router getInstance() {
        if (instance == null) {
            synchronized (Router.class) {
                if (instance == null) {
                    instance = new Router();
                }
            }
        }
        return instance;
    }

    private ARouter _getARouter() {
        return ARouter.getInstance();
    }

    public static ARouter getARouter() {
        return ARouter.getInstance();
    }


    public MyPostcard build(String path) {
        return new MyPostcard(_getARouter().build(path));
    }

    public static <T> T getProvider(Class<? extends T> service) {
        return getARouter().navigation(service);
    }

    /** @noinspection unchecked*/
    public static <T> T getProvider(String path, @NonNull Class<? extends T> service) {
        Object navigation = ARouter.getInstance().build(path).navigation();
        if(canCastTo(navigation,service)){
            return (T) navigation;
        }
        return null;
    }

    /**
     * 根据路由地址获取页面类
     *
     * @param path
     * @return
     */
    public static Class<?> getClassByPath(String path) {
        try {
            Postcard postcard = getARouter().build(path);
            LogisticsCenter.completion(postcard);
            return postcard.getDestination();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取Fragment
     *
     * @param path
     * @param bundle args
     * @return
     */
    public static Fragment createNewFragment(String path, Bundle bundle) {
        Object obj = getInstance().build(path).with(bundle).navigation();
        if (obj instanceof Fragment) {
            return (Fragment) obj;
        } else {
            return null;
        }
    }

    /**
     * 获取Fragment
     *
     * @param path
     * @return
     */
    public static Fragment createNewFragment(String path) {
        return createNewFragment(path, null);
    }

    /**
     * 发现或者创建新的Fragment
     *
     * @param fragmentManager
     * @param path            路由,Tag
     * @return
     */
    public static Fragment findOrCreateByTag(FragmentManager fragmentManager, String path) {
        if (path == null) {
            return null;
        }
        Fragment fragment = fragmentManager.findFragmentByTag(path);
        if (fragment == null) {
            fragment = createNewFragment(path);
            Logger.d(TAG, "创建新的:" + fragment);
        }
        return fragment;
    }


    //>>>>>>>>>>>>>>>>>以下是原生封装>>>>>>>>>>>>>>>>>>>>>>>


    /**
     * 发现或者创建新的Fragment
     *
     * @param cls
     * @param fm
     * @param <T>
     * @return
     */

    public static <T extends Fragment> T findOrCreateByTag(FragmentManager fm, Class<T> cls) {
        return findOrCreateByTag(fm, cls, null);
    }

    /**
     * 发现或者创建新的Fragment
     *
     * @param fm
     * @param cls
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Fragment> T findOrCreateByTag(FragmentManager fm, Class<T> cls, String tag) {
        if (tag == null) {
            tag = cls.getCanonicalName();
        }
        T fragmentByTag = (T) fm.findFragmentByTag(tag);
        if (fragmentByTag == null) {
            try {
                fragmentByTag = cls.newInstance();

                Logger.d(TAG, "findOrCreateByTag: 创建新的" + cls.getName());
            } catch (IllegalAccessException | InstantiationException e) {
                e.printStackTrace();
            }
        } else {
            Logger.d(TAG, "findOrCreateByTag: 复用:" + fragmentByTag);
        }
        return fragmentByTag;
    }

    /**
     * 启动activity
     *
     * @param context
     * @param cls
     */
    public static void navigation(Context context, Class cls) {
        navigation(context, cls, null);
    }


    /**
     * 启动activity
     *
     * @param context
     * @param cls
     * @param bundle
     */
    public static void navigation(Context context, Class cls, Bundle bundle) {
        Intent intent = new Intent(context, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        context.startActivity(intent);
    }

    /**
     * 启动activity
     *
     * @param activity
     * @param cls
     * @param bundle
     * @param requestCode
     */
    @Deprecated
    public static void navigation(Activity activity, Class cls, Bundle bundle, int requestCode) {
        Intent intent = new Intent(activity, cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        activity.startActivityForResult(intent, requestCode);
    }

    /**
     * 启动activity
     *
     * @param activity
     * @param cls
     * @param requestCode
     */
    @Deprecated
    public static void navigation(Activity activity, Class cls, int requestCode) {
        navigation(activity, cls, null, requestCode);
    }

    /**
     * 启动activity
     *
     * @param fragment
     * @param cls
     * @param bundle
     * @param requestCode
     */
    @Deprecated
    public static void navigation(Fragment fragment, Class cls, Bundle bundle, int requestCode) {
        Intent intent = new Intent(fragment.getContext(), cls);
        if (bundle != null) {
            intent.putExtras(bundle);
        }
        fragment.startActivityForResult(intent, requestCode);
    }

    /**
     * 启动activity
     *
     * @param fragment
     * @param cls
     * @param requestCode
     */
    @Deprecated
    public static void navigation(Fragment fragment, Class cls, int requestCode) {
        navigation(fragment, cls, null, requestCode);
    }

    /**
     * 是否可以转换成指定的类型
     * @param data
     * @param clazz
     * @return
     */
    private static boolean canCastTo(Object data, @NonNull Class<?> clazz) {
        //a对象所对应类信息是b对象所对应的类信息的父类或者是父接口，简单理解即a是b的父类或接口
        //a和b为同一个类或同一个接口
        return data!=null && clazz.isAssignableFrom(data.getClass());
    }
}
